

package ru.samgtu.wst.plugin.proxy;

// import org.owasp.util.StringUtil;

import ru.samgtu.wst.httpclient.HTTPClient;
import ru.samgtu.wst.model.Preferences;
import ru.samgtu.wst.model.Request;
import ru.samgtu.wst.model.Response;
import ru.samgtu.wst.plugin.proxy.ProxyPlugin;

import java.io.IOException;
import java.util.regex.Pattern;
import java.util.regex.Matcher;


public class RevealHidden extends ProxyPlugin {

	private boolean _enabled = false;

	/** Creates a new instance of RevealHidden */
	public RevealHidden() {
		parseProperties();
	}

	public void parseProperties() {
		String prop = "RevealHidden.enabled";
		String value = Preferences.getPreference(prop, "false");
		_enabled = ("true".equalsIgnoreCase(value) || "yes"
				.equalsIgnoreCase(value));
	}

	@Override
	public String getPluginName() {
		return new String("Reveal Hidden");
	}

	public void setEnabled(boolean bool) {
		_enabled = bool;
		String prop = "RevealHidden.enabled";
		Preferences.setPreference(prop, Boolean.toString(bool));
	}

	public boolean getEnabled() {
		return _enabled;
	}

	@Override
	public HTTPClient getProxyPlugin(HTTPClient in) {
		return new Plugin(in);
	}

	private class Plugin implements HTTPClient {

		private HTTPClient _in;

		public Plugin(HTTPClient in) {
			_in = in;
		}

		public Response fetchResponse(Request request) throws IOException {
			Response response = _in.fetchResponse(request);
			if (_enabled) {
				String ct = response.getHeader("Content-Type");
				if ((ct != null) && ct.matches("text/.*")) {
					byte[] content = response.getContent();
					if (content != null) {
						response.setContent(revealHidden(content));
						response.addHeader("X-RevealHidden",
								"possibly modified");
					}
				}
			}
			return response;
		}

		private byte[] revealHidden(byte[] content) {
			/*
			 * We split this pattern into two parts, one before "hidden" and one
			 * after Then it is simple to concatenate part 1 + "text" + part 2
			 * to get an "unhidden" input tag
			 */
			Pattern inputPattern = Pattern.compile(
					"(<input.+?type\\s*=\\s*[\"']{0,1})hidden([\"']{0,1}.+?>)",
					Pattern.CASE_INSENSITIVE);
			Matcher inputMatcher = inputPattern.matcher(new String(content));
			StringBuffer outbuf = new StringBuffer();

			/* matched hidden input parameter */
			while (inputMatcher.find()) {
				String input = inputMatcher.group();
				String name = "noname";

				// extract hidden field name
				Pattern namePattern = Pattern.compile(
						"name=[\"']{0,1}(\\w+)[\"']{0,1}",
						Pattern.CASE_INSENSITIVE);
				Matcher nameMatcher = namePattern.matcher(input);
				if (nameMatcher.find() && (nameMatcher.groupCount() == 1)) {
					name = nameMatcher.group(1);
				}

				// make hidden field a text field - there MUST be 2 groups
				// Note: this way we don't have to care about which quotes are
				// being used
				input = inputMatcher.group(1) + "text" + inputMatcher.group(2);

				/* insert [hidden] <fieldname> before the field itself */
				inputMatcher.appendReplacement(outbuf,
						"<STRONG style=\"background-color: white;\"> [hidden field name =\""
								+ name + "\"]:</STRONG> " + input + "<BR/>");
			}
			inputMatcher.appendTail(outbuf);
			return outbuf.toString().getBytes();
		}

	}

}
